import {
  getMinIOFilePath,
  getFileName,
  getOnlyUid,
} from '@/utils/common';
import {

  getUpldUrl,
  chunkMerge,
  getUpFileUrl,
  saveUpSfile
} from '@/api/minIOupload';
import {
  isStudent, isTeach,
} from '@/utils/auth';
import {
  ElMessage,
} from 'element-plus';
import SparkMD5 from 'spark-md5';
import axios from 'axios';
import uploadStore from '@/store/modules/upload'
const uploadArr = ref([])
const uploadUrls = ref([])
//获取uploadId
export function GetQueryValue1(queryName, str) {
  var reg = new RegExp('(^|&)' + queryName + '=([^&]*)(&|$)', 'i');
  let index = str.indexOf('?');
  let r = str.substring(index + 1).match(reg);
  if (r != null) {
    return decodeURI(r[2]);
  } else {
    return null;
  }
}


/**
 * minio上传图片或者视频的方法，从此开始
 */
const FileStatus = {
  wait: '等待上传',
  getMd5: '校验MD5',
  uploading: '正在上传',
  success: '上传成功',
  error: '上传错误',
};
const chunkSize = 10 * 1024 * 1024;
let uploadIdInfo = null;
const FILE_UPLOAD_ID_KEY = 'file_upload_id';
// 上传并发数
const simultaneousUploads = 3;
let myUploadFile = null;


//获取小文件上传的url方法
const getSFileUploadUrls = (fileParams) => {
  return getUpFileUrl(fileParams);
};



// 获取大文件文件的urls
const getFileUploadUrls = (fileParam) => {
  return getUpldUrl(fileParam);
};




//上传图片到minio
export function UploadPicMin(file, blob) {
  const currentFile = file;
  // 当上传文件小于5M
  if (currentFile.size / 1024 / 1024 <= 5) {
    return new Promise(async (resolve, reject) => {
      // 第一步:获取小文件上传的url
      let params = {
        "original_filename": currentFile.name,
        "content_length": currentFile.size
      }
      let uploadIdInfoResult = await getSFileUploadUrls(params) 
      //第二步  上传
      let uploadUrl = uploadIdInfoResult[0]
      let uploadId = uploadIdInfoResult[1]

      if (uploadIdInfoResult.length) {
        // 直接上传二进制，不需要构造 FormData，否则上传后文件损坏
        axios.put(uploadUrl, blob, {
          // 上传进度处理
          headers: {
            'Content-Type': 'application/octet-stream',
          },
        }).then(response => {
          // 第三步 将文件保存到数据库
          saveUpSfile(uploadId).then(result => {
            resolve(result);
          })
        }).catch(error => {
          console.log("上传失败" + error);
        })

      }

    })
  } else {
    return new Promise(async (resolve, reject) => {
      // 文件大于5M走分片上传
      // 1.创建分片(10M一个分片,返回blob格式 数组)
      initFileProperties(file);
      myUploadFile = file;
      let fileChunks = createFileChunk(currentFile, chunkSize);
      if (!fileChunks) return;
      //  分片上传
      let params = {
        content_length: currentFile.size,
        file_name: currentFile.name,
        mime: null
      }

      // 2、获取上传文件的urls
      getFileUploadUrls(params).then(res => {
        // 当前操作文件的地址
        // 分片数组
        uploadIdInfo = res;
        uploadUrls.value = uploadIdInfo[0];
   
        
        if (fileChunks.length !== uploadUrls.value.length) {
          ElMessage.error("文件分片上传地址获取错误");
          return;
        }
        // 分片上传地址没有问题进行下一步
        // 将blob格式的分片添加到当前操作文件中
        fileChunks.map((chunkItem, index) => {
          currentFile.chunkList.push({
            chunkNumber: index + 1,
            chunk: chunkItem,
            uploadUrl: uploadUrls.value[index].url,
            progress: 0,
            status: "—",
          });
        });
        let tempFileChunks = [];
        currentFile.chunkList.forEach((item) => {
          tempFileChunks.push(item);
        });
        currentFile.status = FileStatus.uploading;
        // 处理分片列表，删除已上传的分片
        tempFileChunks = processUploadChunkList(tempFileChunks);
        // 3. 上传
        uploadChunkBase(tempFileChunks);
        watch(uploadArr.value, nv => {
          if (nv.length == uploadUrls.value.length) {
            console.log("分片已全部上传");
            // 4. 合并分片
            let options = uploadIdInfo[1];        
            mergeFile(options).then(res => {       
              if (res.status == "上传成功") {
                ElMessage.success("上传成功");
                currentFile.status = FileStatus.success;
                currentFile.uploadProgress = 100;
                currentFile.file_id = res.file_id
                resolve(res);

              } else {
                // 未上传
                console.log("未上传");
              }

            })
          }
        })
      });



    })


  }
}


//新上传文件初始化
const initFileProperties = (file) => {
  file.chunkList = [];
  file.status = FileStatus.wait;
  file.progressStatus = 'warning';
  file.uploadProgress = 0;
};


/**
 * 上传下标偏移
 */
const autoNextUpload = (files) => {
  currentFileIndex++;
  if (currentFileIndex < files.length) {
    handleUpload();
  }
};

/**
 * 文件分片
 */
const createFileChunk = (file, size = chunkSize) => {
  console.log(size);
  const fileChunkList = [];
  let count = 0;
  if (file.size < 1) return ElMessage.warning('不可上传空文件')
  while (count < file.size) {
    fileChunkList.push({
      file: file.slice(count, count + size),
    });
    count += size;
  }
  return fileChunkList;
};



/**
 * 保存uploadid到缓存
 */
const saveFileUploadId = (data) => {
  localStorage.setItem(FILE_UPLOAD_ID_KEY, data);
};


/**
 * 处理即将上传的分片列表，判断是否有已上传的分片，有则从列表中删除
 */
const processUploadChunkList = (chunkList) => {
  const currentFile = myUploadFile;
  let chunkUploadedList = currentFile.chunkUploadedList;
  if (chunkUploadedList === undefined || chunkUploadedList === null || chunkUploadedList.length === 0) {
    return chunkList;
  }
  //
  for (let i = chunkList.length - 1; i >= 0; i--) {
    const chunkItem = chunkList[i];
    for (let j = 0; j < chunkUploadedList.length; j++) {
      if (chunkItem.chunkNumber === chunkUploadedList[j]) {
        chunkList.splice(i, 1);
        break;
      }
    }
  }
  return chunkList;
};


/**
 * 上传
 */
const uploadChunkBase = (chunkList) => {
  uploadArr.value = []
  let successCount = 0;
  let totalChunks = chunkList.length;
  return new Promise((resolve) => {
    const handler = () => {

      if (chunkList.length) {
        const chunkItem = chunkList.shift();
        if (chunkItem.stop) {
          return;
        }
        // 直接上传二进制，不需要构造 FormData，否则上传后文件损坏
        axios.put(chunkItem.uploadUrl, chunkItem.chunk.file, {
          // 上传进度处理
          onUploadProgress: checkChunkUploadProgress(chunkItem),
          headers: {
            "Content-Type": "application/octet-stream",
          },
        })
          .then((response) => {

            if (response.status === 200) {
              console.log("分片：" + chunkItem.chunkNumber + " 上传成功");
              successCount++;
              // 继续上传下一个分片
              handler();
            } else {
              console.log(
                "上传失败：" + response.status + "，" + response.statusText
              );
            }
            uploadArr.value.push(response)
          })
          .catch((error) => {
            if (!uploadFileList.value.length) return;
            if (chunkItem.stop) {
              return;
            }
            // 更新状态
            ElMessage.error(
              "分片：" + chunkItem.chunkNumber + " 上传失败" + error
            );
            // throw '结束上传'
            // console.log(uploadFileList.value)
            // 重新添加到队列中
            chunkList.push(chunkItem);
            handler();
          });
      }
      if (successCount >= totalChunks) {
        resolve();
      }
    };
    // 并发
    for (let i = 0; i < simultaneousUploads; i++) {
      handler();
    }
  });
};



/**
 * 检查分片上传进度
 */
const checkChunkUploadProgress = (item) => {
  return p => {
    item.progress = parseInt(String((p.loaded / p.total) * 100));


    if (item.stop) return;
    updateChunkUploadStatus(item);
  };
};
const updateChunkUploadStatus = (item) => {
  let status = FileStatus.uploading;
  let progressStatus = 'normal';
  if (item.progress >= 100) {
    status = FileStatus.success;
    progressStatus = 'success';
  }
  let chunkIndex = item.chunkNumber - 1;
  let currentChunk = myUploadFile.chunkList[chunkIndex];
  
  // 修改状态

  console.log(status);
  
  currentChunk.status = status;
  currentChunk.progressStatus = progressStatus;
  // 更新状态
  // this.$set(this.uploadFileList.value[currentFileIndex].chunkList, chunkIndex, currentChunk)
  // 获取文件上传进度
  getCurrentFileProgress();
};

const getCurrentFileProgress = () => {
  const currentFile = myUploadFile;
  if (!currentFile || !currentFile.chunkList) {
    return;
  }
  const chunkList = currentFile.chunkList;
  const uploadedSize = chunkList.map((item) => item.chunk.file.size * item.progress).reduce((acc, cur) => acc + cur);
  // 计算方式：已上传大小 / 文件总大小
  let progress = parseInt((uploadedSize / currentFile.size).toFixed(2));
  currentFile.uploadProgress = progress;
  uploadStore().setVideoProgress(currentFile.uploadProgress)
  // this.$set(this.uploadFileList, currentFileIndex, currentFile)
};


/**
 * 合并文件
 */
const mergeFile = (params) => {
  return new Promise((resolve, reject) => {
    chunkMerge(params)
      .then((res) => {
        if (!res) {
          params.status = FileStatus.error;
          params.file_id = res
          resolve(params);
        } else {
          params.status = FileStatus.success;
          params.file_id = res
          resolve(params);
        }
      })
      .catch((error) => {
        ElMessage.error("合并文件失败：" + error);
        params.status = FileStatus.error;
        reject();
      });
  });
};
